
/*
 * Copyright (C) 2008-2009 Archie L. Cobbs. All rights reserved.
 *
 * $Id: BigIntegerField.java 377 2010-03-11 20:50:18Z archie.cobbs $
 */

package org.dellroad.sidekar;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.math.BigInteger;

import org.dellroad.sidekar.util.PackedLong;
import org.dellroad.stuff.string.ParseContext;

/**
 * {@link BigInteger} field.
 *
 * Support is limited to values having a {@link BigInteger#toByteArray byte array} length of at most {@link #MAXIMUM_BYTE_LENGTH}.
 *
 * @see org.dellroad.sidekar.annotation.SidekarField
 */
public final class BigIntegerField extends AtomicField<BigInteger> {

    BigIntegerField(String name, Entity<?> entity) {
        super(name, entity, BigInteger.class);
    }

    @Override
    public void visit(FieldSwitch fieldSwitch) {
        fieldSwitch.caseBigIntegerField(this);
    }

    @Override
    public void encode(DataOutputStream output, BigInteger value) throws IOException {
        int signum = value.signum();
        byte[] magnitude = value.abs().toByteArray();
        PackedLong.write(output, magnitude.length * signum);
        output.write(magnitude);
    }

    @Override
    public BigInteger decode(DataInputStream input) throws IOException {
        int maglen = (int)PackedLong.read(input);
        int signum = maglen < 0 ? -1 : maglen > 0 ? 1 : 0;
        maglen = maglen * signum;
        byte[] magnitude = new byte[maglen];
        input.readFully(magnitude);
        return new BigInteger(signum, magnitude);
    }

    @Override
    public String toString(BigInteger value) {
        return String.valueOf(value);
    }

    @Override
    public BigInteger fromString(ParseContext ctx) {
        if (ctx.tryLiteral("null"))
            return null;
        BigInteger bigint = new BigInteger(ctx.matchPrefix("-?[0-9]+").group());
        return bigint;
    }
}

